Skip to content

Experimental: Replace Yajl to JSON for handling JSON stream#5383

Draft
Watson1978 wants to merge 3 commits into
fluent:masterfrom
Watson1978:json-resumable-parser
Draft

Experimental: Replace Yajl to JSON for handling JSON stream#5383
Watson1978 wants to merge 3 commits into
fluent:masterfrom
Watson1978:json-resumable-parser

Conversation

@Watson1978

@Watson1978 Watson1978 commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Which issue(s) this PR fixes:
Fixes #

What this PR does / why we need it:
An experiment to replace Yajl with JSON by leveraging ruby/json#994.

TODO

  • Ensure all CI tests pass
  • Check for memory leaks
    • Ensure that the memory usage of JSON::ResumableParser does not grow continuously during long-running stream parsing.
  • Test several edge cases for chunk boundaries
    • Chunk split in the middle of a Unicode escape sequence (e.g., \uXXXX).
    • Chunk split in the middle of primitive values (number, boolean, null):
      • e.g., {"key": tr and ue}
      • e.g., {"key": 12 and 34.56}
    • Parser recovery
      • Check whether the parser can successfully parse the next valid JSON chunk right after a JSON::ParserError is raised from a malformed chunk.

Docs Changes:

Release Note:

@Watson1978 Watson1978 marked this pull request as draft June 9, 2026 08:00
@Watson1978 Watson1978 force-pushed the json-resumable-parser branch 6 times, most recently from ce836b7 to aa55407 Compare June 9, 2026 09:03
Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
@Watson1978 Watson1978 force-pushed the json-resumable-parser branch 2 times, most recently from f42a6b3 to 8afdc66 Compare June 17, 2026 04:21
Signed-off-by: Shizuo Fujita <fujita@clear-code.com>
@Watson1978 Watson1978 force-pushed the json-resumable-parser branch from 8afdc66 to 9fad78d Compare June 17, 2026 04:36
@Watson1978

Copy link
Copy Markdown
Contributor Author

Performance Comparison: yajl-ruby vs JSON::ResumableParser

I conducted a performance test to evaluate the efficiency of JSON::ResumableParser compared to the current yajl-ruby implementation.

Test Scenario

  • A client sends a continuous stream of ~1MB JSON messages via TCP at fixed 100ms intervals (approx. 10 MB/s).
  • Monitored CPU and Memory (RSS) usage of the receiver during processing.

Results (Handling ~10 MB/s constant load)

  • yajl-ruby

    • CPU Usage: ~70% (Average)
    • Memory (Max RSS): ~126 MB
  • JSON::ResumableParser

    • CPU Usage: ~5% (Average)
    • Memory (Max RSS): ~127 MB

JSON::ResumableParser processes the same data stream vastly more efficiently than yajl-ruby. While memory consumption remains nearly identical, the new parser reduces CPU usage from ~70% to just ~5% under the same load. This massive reduction in CPU overhead indicates that ResumableParser provides significantly higher potential throughput and overall resource efficiency in stream processing environments.

Code_Generated_Image

Fluentd conf

<source>
  @type forward
  bind "0.0.0.0"
  port 24224
</source>

<match **>
  @type null
</match>

Client script

require 'socket'
require 'json'
require 'time'
require 'securerandom'

host = '127.0.0.1'
port = 24224

puts "Connecting to #{host}:#{port}..."
sock = TCPSocket.new(host, port)

loop do
  msg = [
    "test.memory",
    Time.now.to_i,
    {
      "id" => SecureRandom.uuid,
      "message" => "This is a memory test for JSON::ResumableParser",
      "dummy_data" => ('a'..'z').to_a.sample * 1024 * 1024
    }
  ]

  json_str = JSON.generate(msg)
  sock.write(json_str)
  sleep 0.1
end

sock.close

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant